/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.polimi.timer.business.weatherclient;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.ejb.Schedule;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.json.JSONException;
import org.json.JSONObject;
import com.polimi.meteocal.business.control.PartecipationManager;
import com.polimi.meteocal.business.entity.Event;
import com.polimi.meteocal.business.entity.Notification;
import com.polimi.meteocal.business.entity.User;
import com.polimi.meteocal.business.entity.Weather;
import com.polimi.timer.business.weather.util.JsonWeatherUtil;
import com.polimi.timer.business.weather.util.WeatherUtil;

/**
 *
 * @author miglie
 */
@Startup
@Singleton
public class WeatherManager {   
	@EJB
	PartecipationManager pm;
	
	@PersistenceContext
    EntityManager em;
	//*** Contains the list of conditions where the user must be notified ***
	private ArrayList<String>badConditions;
    @PostConstruct
    private void init() { 
    	badConditions=new ArrayList<String>();
    	badConditions.add("Snow");
    	badConditions.add("Rain");
    	
    	
    }
    //*** Update forecast for every Event in Database, and set Notification for
    //	  partecipants and organizers ***
    @Schedule(second = "*/5", minute = "*", hour = "*", persistent = false)
    public void UpdateForecastAutoTimer() {
    	Date nowtimestamp=new Date();
        List<Event> events=this.em
                              .createNamedQuery(Event.FIND_ALL, Event.class).getResultList();                
        for(Event event:events){
        	long diff=event.getDatetimebegin().getTime()-nowtimestamp.getTime();
        	if((diff>0)&&(diff<1296000000)){
	            try {
	            	JSONObject forecast=WeatherUtil.getForecast(event.getPlace(), event.getDatetimebegin());
	            	
	            	if(forecast != null){
		                this.ForecastSetter(event, forecast);	                
	            	}
	            } catch (JSONException e) {
	                    e.printStackTrace();
	            } catch (IOException e) {
	                    e.printStackTrace();
	            }
	        	
	            
	        	this.PartecipantNotificationSetter(event);
	        	this.OrganizerNotificationSetter(event);
        	}
        }
        
    }
    //Set Event Object with JSON Object returned by call API
    public void ForecastSetter(Event event, JSONObject forecast){
		Weather weather= new Weather();
		weather.setEventId(event.getId());
		weather.setTemperature(JsonWeatherUtil.getTemperature(forecast, WeatherUtil.ModeFetchingSelector(event.getDatetimebegin())));
		weather.setCondition(JsonWeatherUtil.getWeatherType(forecast, WeatherUtil.ModeFetchingSelector(event.getDatetimebegin())));
		event.setWeather(weather);
		em.merge(event);
		em.flush();
	}
    //*** Save Partecipants Notification ***
	public void PartecipantNotificationSetter(Event event){
		List<User>partecipants=pm.getPartecipants(event.getId());
		Date date = new Date();
        long diff = event.getDatetimebegin().getTime() - date.getTime(); 
        long diffHours = diff / (60 * 60 * 1000);
        if(diffHours<24){
        	if(badConditions.contains(event.getWeather().getCondition())){
        		for(User usr:partecipants){
        			Notification notification=new Notification();
        			notification.setUser(usr);
        			notification.setCondition(event.getWeather().getCondition());
        			event.addNotification(notification);
        			
        			this.em.merge(event);
        			this.em.flush();
        		}        		      		
        	}
        }
	}
	//*** Save Organizers Notification ***
	public void OrganizerNotificationSetter(Event event){
		@SuppressWarnings("unchecked")
		List<String>organizersId=this.em
    			.createNativeQuery("SELECT USER_MAIL FROM ORGANIZER WHERE EVENT_ID = '"+Integer.toString(event.getId())+"'").getResultList();
		List<User>organizers=new ArrayList<User>();
		for(String org : organizersId){
			organizers.add(this.em.find(User.class, org));
		}
		
		Date date = new Date();
        long diff = event.getDatetimebegin().getTime() - date.getTime(); 
        long diffHours = diff / (60 * 60 * 1000);
        if(diffHours<72){
        	if(badConditions.contains(event.getWeather().getCondition())){
        		for(User usr:organizers){
        			Notification notification=new Notification();
        			notification.setUser(usr);
        			notification.setCondition(event.getWeather().getCondition());
        			event.addNotification(notification);
        			
        			this.em.merge(event);
        			this.em.flush();
        		}        		      		
        	}
        }
	}
}
